今天一樣是簡單的 SLT、SLTU 指令實作,
並為了 Code Stream Logger 做準備,
唯一有趣的是遇到 g++ 未實做的 feature 導致編譯錯誤,
只好改用別種方式實做。
指令格式如下:
|31     25|24   20|19   15|14    12|11   7|6       0|
+---------------------------------------------------+
|  func7  |  rs2  |  rs1  | funct3 |  rd  | opcode  |
+---------------------------------------------------+
rd = rs1 < rs2 ? 1 : 0
|31         25|24   20|19   15|14    12|11   7|6       0|
+-------------------------------------------------------+
|   0000000   |  rs2  |  rs1  |  010   |  rd  | 0110011 |
+-------------------------------------------------------+
rd = (uint32_t)rs1 < (uint32_t)rs2 ? 1 : 0
|31         25|24   20|19   15|14    12|11   7|6       0|
+-------------------------------------------------------+
|   0000000   |  rs2  |  rs1  |  011   |  rd  | 0110011 |
+-------------------------------------------------------+
github 頁面 Tag: ITDay24
RISC-V-TLM 的 Logger 設計不太適合接下來的模擬用途,
作者客製化每道指令的 Log 內容,為了可讀性犧牲了一致性,
這樣的設計也在維護上容易有一些小疏失,
接下來實做的時候會嘗試重新設計 Logger 的部分,
這次先把 Code Stream Logger 需要用到的指令和指令名稱列出來。
Instruction Name 需要從數字一對一對應到字串,本來想用 std::array 做,
和 exactstep 類似,結果遇到了 g++ 很有禮貌的說:sorry, unimplemented: non-trivial designated initializers not supported
先改用 std::map 實做。
//instructionDecoderInterface.h
...
	enum Instruction {
		ADDI_INSTRUCTION_ENUM,
		ANDI_INSTRUCTION_ENUM,
		ORI_INSTRUCTION_ENUM,
		XORI_INSTRUCTION_ENUM,
...
	std::map<Instruction, std::string> instruction_name_map = {
		{ADDI_INSTRUCTION_ENUM,"ADDI"},
		{ANDI_INSTRUCTION_ENUM,"ANDI"},
		{ORI_INSTRUCTION_ENUM,"ORI"},
		{XORI_INSTRUCTION_ENUM,"XORI"},
...
指令實作:
//instructionDecoderInterface.h
...
		SLT_FN3 = 0b010,
		SLTU_FN3 = 0b011,
...
		SLT_FN7 = 0b0000000,
		SLTU_FN7 = 0b0000000,
...
//executor.cpp
...
		case INSTRUCTION_DECODER_INTERFACE::SLT_FN3:
			SLT_E();
			//do not check FN7 for readibility, refactor in future
			break;
		case INSTRUCTION_DECODER_INTERFACE::SLTU_FN3:
			SLTU_E();
			//do not check FN7 for readibility, refactor in future
			break;
...
void EXECUTOR::SLT_E()
{
	auto rd = instruction_decoder->get_rd();
	auto rs1 = instruction_decoder->get_rs1();
	auto rs2 = instruction_decoder->get_rs2();
	auto value = register_file->get_value_integer(rs1) < register_file->get_value_integer(rs2) ? 1 : 0;
	register_file->set_value_integer(rd, value);
}
void EXECUTOR::SLTU_E()
{
	auto rd = instruction_decoder->get_rd();
	auto rs1 = instruction_decoder->get_rs1();
	auto rs2 = instruction_decoder->get_rs2();
	auto value = (uint32_t)register_file->get_value_integer(rs1) < (uint32_t)register_file->get_value_integer(rs2) ? 1 : 0;
	register_file->set_value_integer(rd, value);
}
...